package com.bizframework.springhb.support.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.bizframework.core.domain.BaseDao;
import com.bizframework.core.domain.BaseEntity;
import com.bizframework.core.domain.ListResult;
import com.bizframework.core.domain.QueryCondition;
import com.bizframework.core.domain.SortInfo;
import com.bizframework.springhb.support.util.Utils;

public class BaseDaoHBImpl<T extends BaseEntity<IDT>, IDT extends Serializable> extends
		HibernateDaoSupport implements BaseDao<T, IDT> {

	protected Class<T> entityClass;
	
	protected Log log = LogFactory.getLog(getClass());

	@SuppressWarnings("unchecked")
	public BaseDaoHBImpl() {
		super();
		if (((ParameterizedType) getClass().getGenericSuperclass())
				.getActualTypeArguments()[0] != null) {
			entityClass = (Class<T>) ((ParameterizedType) getClass()
					.getGenericSuperclass()).getActualTypeArguments()[0];
		}
	}

	public void delete(T entity) throws Exception {
		getHibernateTemplate().delete(entity);
	}

	public void flush() throws Exception {
		getHibernateTemplate().flush();
	}

	@SuppressWarnings("unchecked")
	public List<T> getAll() throws Exception {
		if (entityClass == null) {
			throw new Exception("entityClass为空。");
		}
		return getHibernateTemplate().loadAll(entityClass);
	}

	public ListResult<T> getByConditionsWithCount(
			List<QueryCondition> conditions, int startIndex, int count,
			SortInfo sortInfo) throws Exception {
		int total = getCountByConditions(conditions);
		List<T> list = getByConditions(conditions, startIndex, count, sortInfo);
		return new ListResult<T>(total, list);
	}

	@SuppressWarnings("unchecked")
	public List<T> getByConditions(List<QueryCondition> conditions,
			int startIndex, int count, SortInfo sortInfo) throws Exception {
		Query query = createQuery(conditions, sortInfo);
		if (count > 0) {
			query.setFirstResult(startIndex);
			query.setMaxResults(count);
		}
		List<T> results = query.list();
		return results;
	}

	@SuppressWarnings("unchecked")
	public List<T> getByConditions(List<QueryCondition> conditions,
			SortInfo sortInfo) throws Exception {
		Query query = createQuery(conditions, sortInfo);

		List<T> results = query.list();
		return results;
	}

	@SuppressWarnings("unchecked")
	public T getById(IDT entityId) throws Exception {
		if (entityClass == null) {
			throw new Exception("entityClassΪ�ա�");
		}
		return (T) getHibernateTemplate().get(entityClass,
				(Serializable) entityId);
	}

	public int getCountByConditions(List<QueryCondition> conditions)
			throws Exception {
		if (entityClass == null) {
			throw new Exception("entityClassΪ�ա�");
		}
		String alias = entityClass.getName().toLowerCase().replace(".", "_");
		String hql = "Select count(*) From " + entityClass.getName() + " as "
				+ alias + " Where 1=1 ";

		Query query = Utils.createQuery(getSession(), hql, null, alias, conditions, null);
		Object o = query.uniqueResult();
		return o == null ? 0 : Integer.parseInt(o.toString());
	}

	public void loadData(Object proxy) throws Exception {
		getHibernateTemplate().initialize(proxy);
	}

	public void refresh(T entity) throws Exception {
		getHibernateTemplate().refresh(entity);
	}

	public void save(T entity) throws Exception {
		getHibernateTemplate().save(entity);
	}

	public void saveOrUpdate(T entity) throws Exception {
		getHibernateTemplate().saveOrUpdate(entity);
	}

	public void update(T entity) throws Exception {
		getHibernateTemplate().update(entity);
	}

	public List<T> findBy(String name, Object value) throws Exception {
		return findBy(new String[] { name }, new Object[] { value });
	}

	@SuppressWarnings("unchecked")
	public List<T> findBy(String[] names, Object[] values) throws Exception {
		if (names == null || values == null || names.length != values.length) {
			// throw new Exception();
			return null;
		}
		Criteria criteria = getCriteria();
		Map<String, Object> criteriaMap = new HashMap<String, Object>();
		for (int i = 0; i < names.length; i++) {
			criteriaMap.put(names[i], values[i]);
		}
		criteria.add(Restrictions.allEq(criteriaMap));
		return criteria.list();
	}

	protected Criteria getCriteria() throws Exception {
		if (entityClass == null) {
			throw new Exception("entityClassΪ�ա�");
		}
		Criteria criteria = getSession().createCriteria(entityClass);
		criteria.setCacheable(true);
		criteria.setCacheRegion("com.framework.core");
		return criteria;
	}
	
	protected Query createQuery(List<QueryCondition> conditions,
			SortInfo sortInfo) throws Exception {
		if (entityClass == null) {
			throw new Exception("entityClass为空");
		}

		String alias = entityClass.getName().toLowerCase().replace(".", "_");
		String hql = "From " + entityClass.getName() + " as " + alias
				+ " Where 1=1";
		return Utils.createQuery(getSession(), hql, null, alias, conditions,
				sortInfo);
	}

	@SuppressWarnings("unchecked")
	public T merge(T entity) {
		return (T) getHibernateTemplate().merge(entity);
	}
}